#ifndef MEMBER_H
#define MEMBER_H
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include "Book.h"

struct Date
{
	std::string year;
	std::string month;
	std::string day;
	
	Date() : year("1900"), month("01"), day("01") {}
	Date(std::string y_, std::string m_, std::string d_) : year(y_), month(m_), day(d_) {}
	Date(std::string str);
	friend std::ostream& operator<<(std::ostream& os, const Date& date)
	{
		os << date.year << "." << date.month << "." << date.day << ".";
		return os;
	}

	Date AddDays(int days) const;
	bool IsBeforeDueDate(Date &dateOfReturn_) const;
	bool IsValidDate() const;
};

struct Loaning
{
	Date dateOfBegin;
	std::string bookID;
	Date dateOfReturn;
	
	Loaning(Date begin_, std::string ID_, Date return_) : dateOfBegin(begin_), bookID(ID_), dateOfReturn(return_) {}

	friend std::ostream& operator<<(std::ostream& os, Loaning *loaning)
	{
		os << "Date of begin: " << loaning->dateOfBegin << "\n" 
		<< "Date of return: " << loaning->dateOfReturn << "\n"
		<< "Book ID: " << loaning->bookID << "\n";
		return os;
	}
};

class Member
{
	public:
		virtual ~Member();
		virtual bool Borrow(Book *book, Date& dateOfBegin_) = 0;
		bool ReturnBook(Book *book, Date& dateOfReturn_);
		std::string GetID() const {return id;}
		std::string GetName() const {return name;}
		std::string GetAddress() const {return address;}
		std::string GetType() const {return type;}
		std::string GetContacts() const {return contacts;}
		std::vector<Loaning*> GetBooksBorrowed() const {return booksBorrowed;}
		void SetName(std::string name_) {name = name_;}
		void SetAddress(std::string address_) {address = address_;}
		void SetType(std::string type_) {type = type_;}
		void SetContacts(std::string contacts_) {contacts = contacts_;}

		friend std::ostream& operator<<(std::ostream& os, Member *member)
		{
			os << "ID: " << member->id << "\n" 
			<< "Name: " << member->name << "\n"
			<< "Address: " << member->address << "\n"
			<< "Type: " << member->type << "\n"
			<< "Contacts: " << member->contacts << "\n"
			<< "Books borrowed:\n";
			for (const auto &borrowedBook : member->booksBorrowed)
				os << borrowedBook;
			os << std::endl;
			return os;
		}
		
	protected:
		Member(std::string name_, std::string address_, std::string type_, std::string contacts_, const std::vector<Loaning*> &booksBorrowed_);
		std::string id;
		std::string name;
		std::string address;
		std::string type;
		std::string contacts;
		std::vector<Loaning*> booksBorrowed;
};

class Student : public Member
{
	public:
		Student(std::string name_, std::string address_, std::string type_, std::string contacts_, const std::vector<Loaning*> &booksBorrowed_) : Member(name_, address_, type_, contacts_, booksBorrowed_) {}
		~Student(){}
		bool Borrow(Book *book, Date& dateOfBegin_);
};

class Teacher : public Member
{
	public:
		Teacher(std::string name_, std::string address_, std::string type_, std::string contacts_, const std::vector<Loaning*> &booksBorrowed_) : Member(name_, address_, type_, contacts_, booksBorrowed_) {}
		~Teacher(){}
		bool Borrow(Book *book, Date& dateOfBegin_);
};

class OtherUnivCitizen : public Member
{
	public:
		OtherUnivCitizen(std::string name_, std::string address_, std::string type_, std::string contacts_, const std::vector<Loaning*> &booksBorrowed_) : Member(name_, address_, type_, contacts_, booksBorrowed_) {}
		~OtherUnivCitizen(){}
		bool Borrow(Book *book, Date& dateOfBegin_);
};

class Other : public Member
{
	public:
		Other(std::string name_, std::string address_, std::string type_, std::string contacts_, const std::vector<Loaning*> &booksBorrowed_) : Member(name_, address_, type_, contacts_, booksBorrowed_) {}
		~Other(){}
		bool Borrow(Book *book, Date& dateOfBegin_);
};

#endif